/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */

/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
function ListNode(val, next) {
  this.val = (val===undefined ? 0 : val)
  this.next = (next===undefined ? null : next)
}

var nodeNext= function(node) {
  let num = 0;
  let isNext = true;
  if (node) {
    num = node.val
    if (node.next) {
      node = node.next;
    } else {
      node = null
      isNext = false
    }
  } else {
    isNext = false
  }
  return {node , isNext, num}
}

// 152 ms
var addTwoNumbers = function(l1, l2) {
  if (!l1 && !l2) return [0]
  let carry = 0;
  let preNode = null;
  let nextNode = null;
  while(1) {
    const node1 = nodeNext(l1);
    const node2 = nodeNext(l2);
    let sum = node1.num + node2.num + carry;
    carry = Math.floor(sum / 10);
    sum = sum % 10;
    // console.log("carry=", carry, ' sum=', sum)
    if (preNode) {
      nextNode.next = new ListNode(sum)
      nextNode = nextNode.next
    } else {
      nextNode = new ListNode(sum)
      preNode = nextNode
    }
    l1 = node1.node;
    l2 = node2.node;
    if (!node1.isNext && !node2.isNext) {
      break;
    }
  }

  if (carry) {
    nextNode.next = new ListNode(carry)
  }

  return preNode;
};


// 执行用时为 116 ms 的范例 -- 参考其他人写的(感觉我写的就啰嗦了)
var addTwoNumbers2 = function(l1, l2) {
  if (!l1) { return l2 }
  if (!l2) { return l1 }
  let res = new ListNode(0, null);
  let carry = 0;
  let current = res;
  while (l1 || l2) {
      let num1 = (l1 === null) ? 0 : l1.val;
      let num2 = (l2 === null) ? 0 : l2.val;
      let sum = num1 + num2 + carry;
      carry = Math.floor(sum / 10);
      current.next = new ListNode(sum % 10);
      current = current.next;
      if (l1 !== null) l1 = l1.next;
      if (l2 !== null) l2 = l2.next;
  }
  if (carry) current.next = new ListNode(1);
  return res.next;
};

// 执行用时为 108 ms 的范例
var addTwoNumbers3 = function(l1, l2) {
  let rest = 0 // carry
  const res = new ListNode()
  let curr = res
  while (l1 || l2 || rest) {
    const sum = (l1?.val ?? 0) + (l2?.val ?? 0) + rest
    rest = ~~(sum / 10)
    curr.next = new ListNode(sum % 10)
    curr = curr.next
    l1 = l1?.next
    l2 = l2?.next
  }
  return res.next
};


// ------------------------------
// test code

const testList = [
  // [2,4,3],
  // [5,6,4]

  // [0],
  // [0]

  [9,9,9,9,9,9,9],
  [9,9,9,9]
]

let createNode = function (list) {
  if (!(list && Array.isArray(list) && list.length)) {
    return null;
  }
  let nextNode = null;
  let preNode = null;
  let length = list.length - 1;
  for (let i = 0; i <= length; i++) {
    if (i == 0) {
      nextNode = new ListNode(list[length], null)
      preNode = nextNode
    } else {
      preNode = new ListNode(list[length - i], nextNode)
      nextNode = preNode
    }
  }
  return preNode
}

function printNodeResult(list) {
  if (!list) {
    console.warn('no value')
    return
  }
  let nodeString = '[' + list.val
  while(list.next) {
    nodeString += ','
    list = list.next;
    nodeString += list.val
  }
  nodeString += ']'
  console.log(nodeString)
}

let createList = function (list) {
  const l1 = createNode(list[0]) || {}
  const l2 = createNode(list[1])
  return {l1, l2}
}

const nodelist = createList(testList);
const l1 = nodelist.l1;
const l2 = nodelist.l2;
console.log(l1)
console.log(l2)
// const result = addTwoNumbers(l1, l2)
// const result = addTwoNumbers2(l1, l2)
const result = addTwoNumbers3(l1, l2)
printNodeResult(result)